package com.echo.yixiaowu.feature.player

import android.content.ComponentName
import android.content.Context
import androidx.annotation.OptIn
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken
import com.echo.yixiaowu.R
import com.echo.yixiaowu.data.model.player.BackendMediaData
import com.echo.yixiaowu.data.model.player.BaseHomeDetailData
import com.echo.yixiaowu.data.model.player.CardContentType
import com.echo.yixiaowu.data.model.player.CardDetailItemData
import com.echo.yixiaowu.data.model.player.CommentData
import com.echo.yixiaowu.service.PlaybackService
import com.google.common.util.concurrent.ListenableFuture
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

/**
 * 卡片详情ViewModel
 */
class MediaViewModel : ViewModel() {
    private val CACHE_DURATION_MS = 10 * 60 * 1000L
    private var playerListener: Player.Listener? = null
    private var controllerFuture: ListenableFuture<MediaController>? = null
    private val _mediaController = MutableStateFlow<MediaController?>(null)
    val mediaController: StateFlow<MediaController?> = _mediaController

    private val _uiState = MutableStateFlow(CardDetailUiState())
    val uiState: StateFlow<CardDetailUiState> = _uiState

    private val _commentUiState = MutableStateFlow(CommentUiState())
    val commentUiState: StateFlow<CommentUiState> = _commentUiState

    private val _mediaUiState = MutableStateFlow(MediaUIState())
    val mediaUiState: StateFlow<MediaUIState> = _mediaUiState

    @OptIn(UnstableApi::class)
    fun initializePlayer(context: Context) {
        // 防止重复初始化
        if (_mediaController.value != null || controllerFuture != null) return

        val sessionToken =
            SessionToken(context, ComponentName(context, PlaybackService::class.java))
        controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
        controllerFuture?.addListener(
            {
                // 当异步构建完成后，更新 StateFlow 的值
                _mediaController.value = controllerFuture?.get()
                // 清理 future 引用
                controllerFuture = null
            }, ContextCompat.getMainExecutor(context)
        )
    }

    private var _currentAspect: Float? = null
    fun computeScreenSize(videoWidth: Int, videoHeight: Int) {
        val newAspectRatio = videoWidth.toFloat() / videoHeight.toFloat()
        val compare = _currentAspect?.let {
            newAspectRatio.compareTo(it) == 0 || abs(newAspectRatio - it) < 1e-6f
        }
        if (compare == true) return
        _currentAspect = newAspectRatio
        val newState = createScreenState(
            _mediaUiState.value.screenWidth,
            _mediaUiState.value.screenHeight,
            videoWidth,
            videoHeight
        )
        viewModelScope.launch {
            _mediaUiState.update {
                it.copy(
                    originalVideoHeight = newState.originalVideoHeight,
                    videoHeight = newState.originalVideoHeight,
                )
            }
        }
    }

    fun initializeScreenState(
        screenWidth: Int, screenHeight: Int, videoWidth: Int, videoHeight: Int
    ) {
        val newState = createScreenState(screenWidth, screenHeight, videoWidth, videoHeight)
        _mediaUiState.update {
            it.copy(
                screenWidth = screenWidth,
                screenHeight = screenHeight,
                videoHeight = newState.originalVideoHeight,
                minimumHeight = newState.minimumHeight
            )
        }
    }

    private fun createScreenState(
        screenWidth: Int, screenHeight: Int, videoWidth: Int, videoHeight: Int
    ): MediaUIState {
        val minimumHeight = min(screenWidth, screenHeight) * 9f / 16f
        val maximumHeight = max(screenWidth, screenHeight) * 2 / 3f
        val originalVideoHeight = (min(
            screenWidth, screenHeight
        ) * videoHeight.toFloat() / videoWidth.toFloat()).coerceIn(minimumHeight, maximumHeight)
        return MediaUIState(
            screenWidth = screenWidth,
            screenHeight = screenHeight,
            videoHeight = originalVideoHeight.dp,
            minimumHeight = minimumHeight.dp
        )
    }

    init {
        viewModelScope.launch {
            mediaController.collect { controller ->
                controller?.let {
                    setupPlayerListener(it)
                }
            }
        }
    }

    private fun setupPlayerListener(controller: MediaController) {
        playerListener?.let { controller.removeListener(it) }
        playerListener = object : Player.Listener {
            override fun onPlaybackStateChanged(playbackState: Int) {
                when (playbackState) {
                    Player.STATE_READY -> {
                        _mediaUiState.update {
                            it.copy(totalDuration = controller.duration)
                        }
                    }

                    Player.STATE_ENDED -> {
                        _mediaUiState.update {
                            it.copy(
                                isPlaying = false,
                                currentDuration = controller.duration,
                                progress = 1f
                            )
                        }
                    }

                    else -> {

                    }
                }
            }

            override fun onIsPlayingChanged(isPlaying: Boolean) {
                _mediaUiState.update {
                    if (isPlaying) {
                        it.copy(isPlaying = true).also {
                            startProgressUpdates()
                        }
                    } else {
                        it.copy(isPlaying = false).also {
                            stopProgressUpdates()
                        }
                    }
                }
            }
        }
        playerListener?.let { controller.addListener(it) }
    }

    private var progressUpdateJob: Job? = null
    private fun startProgressUpdates() {
        progressUpdateJob = CoroutineScope(Dispatchers.Main).launch {
            mediaController.value?.let {
                while (it.isPlaying) {
                    val currentPos = it.currentPosition
                    val duration = it.duration
                    val bufferPos = it.bufferedPosition
                    _mediaUiState.update { media ->
                        media.copy(
                            currentDuration = it.currentPosition,
                            progress = currentPos.toFloat() / duration,
                            bufferProgress = bufferPos.toFloat() / duration
                        )
                    }
                    delay(1000)
                }
            }
        }
    }

    private fun stopProgressUpdates() {
        progressUpdateJob?.cancel()
    }

    override fun onCleared() {
        stopProgressUpdates()
        playerListener?.let { mediaController.value?.removeListener(it) }
        controllerFuture?.let {
            MediaController.releaseFuture(it)
        }
        mediaController.value?.release()
        super.onCleared()
    }

    fun playItem(mediaItem: MediaItem) {
        val controller = _mediaController.value ?: return

        val isSameItem = controller.currentMediaItem?.mediaId == mediaItem.mediaId
        if (isSameItem) {
            controller.play()
        } else {
            controller.stop()
            controller.clearMediaItems()

            controller.setMediaItem(mediaItem)
            controller.prepare()
            controller.play()
        }
    }

    fun processIntent(intent: MediaPageIntent) {
        when (intent) {
            is MediaPageIntent.LoadItemData -> loadItemData(intent.itemId)
            is MediaPageIntent.LoadCommentData -> loadCommentData(intent.itemId)
            is MediaPageIntent.ClickCommentLike -> clickCommentLike(intent.commentId)
            is MediaPageIntent.ClickCommentDislike -> clickCommentDislike(intent.commentId)
            is MediaPageIntent.ClickMediaFavorite -> clickMediaFavorite(intent.isFavorite)
            is MediaPageIntent.ClickMediaExpand -> clickMediaExpand(intent.isExpanded)
            is MediaPageIntent.ClickMediaFullScreen -> clickMediaFullScreen(
                intent.isFullScreen, intent.newHeight
            )

            is MediaPageIntent.ClickMediaDislike -> clickMediaDislike(intent.isDislike)
            is MediaPageIntent.ClickMediaLike -> clickMediaLike(intent.isLike)
            is MediaPageIntent.ClickPlaying -> clickPlaying(intent.isPlaying)
            is MediaPageIntent.ClickShowControls -> clickShowControls(intent.isShow)
            is MediaPageIntent.SetControlVisible -> setControlVisible(intent.isVisible)
            is MediaPageIntent.SeekToProgress -> seekToProgress(intent.progress)
        }
    }

    private fun seekToProgress(progress: Float) {
        val media = mediaController.value!!
        val positionMs = (media.duration * progress).toLong()
        media.seekTo(positionMs)
        viewModelScope.launch {
            _mediaUiState.update {
                it.copy(
                    currentDuration = positionMs,
                    progress = positionMs / media.duration.toFloat()
                )
            }
        }
    }

    private fun setControlVisible(isVisible: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isShowControl = isVisible)
            }
        }
    }

    private fun clickMediaExpand(isExpanded: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isExpanded = !isExpanded)
            }
        }
    }

    private fun clickMediaFullScreen(isFullScreen: Boolean, newHeight: Dp) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isFullScreen = !isFullScreen, videoHeight = newHeight)
            }
        }
    }

    private fun clickMediaFavorite(isFavorite: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isFavorite = !isFavorite)
            }
        }
    }

    private fun clickCommentLike(commentId: String) {
        viewModelScope.launch {
            _commentUiState.update { currentState ->
                val newList = currentState.commentList.map { comment ->
                    if (comment.id == commentId) {
                        comment.copy(
                            isLiked = !comment.isLiked,
                            likeCount = if (comment.isLiked) comment.likeCount - 1 else comment.likeCount + 1,
                            isDisliked = false
                        )
                    } else {
                        comment
                    }
                }
                currentState.copy(commentList = newList)
            }
        }
    }

    private fun clickMediaDislike(isDislike: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isDisliked = !isDislike, isLiked = false)
            }
        }
    }

    private fun clickMediaLike(isLike: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isLiked = !isLike, isDisliked = false)
            }
        }
    }

    private fun clickShowControls(isShow: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isShowControl = !isShow)
            }
        }
    }

    private fun clickPlaying(isPlaying: Boolean) {
        viewModelScope.launch {
            _mediaUiState.update { currentState ->
                currentState.copy(isPlaying = !isPlaying)
            }

            if (isPlaying) {
                mediaController.value?.pause()
            } else {
                mediaController.value?.play()
            }
        }
    }

    private fun clickCommentDislike(commentId: String) {
        viewModelScope.launch {
            _commentUiState.update { currentState ->
                val newList = currentState.commentList.map { comment ->
                    if (comment.id == commentId) {
                        val isDislike = !comment.isDisliked
                        var likeCount = comment.likeCount
                        if (comment.isLiked && isDislike) {
                            likeCount -= 1
                        }
                        comment.copy(
                            isDisliked = isDislike, likeCount = likeCount, isLiked = false
                        )
                    } else {
                        comment
                    }
                }
                currentState.copy(commentList = newList)
            }
        }
    }

    private fun loadCommentData(itemId: String) {
        val currentState = _commentUiState.value
        viewModelScope.launch {
            val now = System.currentTimeMillis()
            val timeSinceLastFetch = now - currentState.fetchDataState.lastFetchedTimestamp
            // 判断是否需要重新请求(使用缓存)
            if (currentState.commentList.isEmpty() || timeSinceLastFetch > CACHE_DURATION_MS) {
                _commentUiState.value = CommentUiState(
                    fetchDataState = FetchBackendDataUiState(
                        isLoading = true,
                    )
                )
                val backendData = fetchCommentData(itemId)
                _commentUiState.value = _commentUiState.value.copy(
                    fetchDataState = FetchBackendDataUiState(false, null, now),
                    commentList = backendData
                )
            }
        }
    }

    private fun loadItemData(itemId: String) {
        viewModelScope.launch {
            // 模拟请求后端
            _uiState.value = CardDetailUiState(fetchDataState = FetchBackendDataUiState(true))
            try {
                val backendData = fetchItemData(itemId)
                val baseData = BaseHomeDetailData(
                    id = backendData.id,
                    type = backendData.type,
                    title = backendData.title,
                    content = backendData.content,
                    commentCount = backendData.commentCount,
                    likeCount = backendData.likeCount,
                    shareCount = backendData.shareCount,
                    favoriteCount = backendData.favoriteCount,
                    author = backendData.author,
                    avatar = backendData.avatar,
                    time = backendData.time
                )

                val itemData = when (backendData.type) {
                    CardContentType.TEXT -> CardDetailItemData.TextItem(baseData)
                    CardContentType.VIDEO -> CardDetailItemData.VideoItem(
                        backendData.videoUrl!!, baseData
                    )
                }
                _uiState.value = _uiState.value.copy(
                    fetchDataState = FetchBackendDataUiState(false, null), itemData = itemData
                )
            } catch (e: Exception) {
                _uiState.value = _uiState.value.copy(
                    fetchDataState = FetchBackendDataUiState(false, "加载失败: ${e.message}"),
                )
            }
        }
    }
}

suspend fun fetchCommentData(itemId: String): List<CommentData> {
    delay(100)
    return List(6) { index ->
        val userNumber = index + 1
        CommentData(
            id = userNumber.toString(),
            authorName = "使用者$userNumber",
            content = when (index) {
                0 -> "这是我见过最棒的！👍"
                1 -> "写的太好了，谢谢你"
                2 -> "楼上讲的很不错"
                3 -> "学会了，先收藏一波，下次再来观摩观摩"
                4 -> "看起来很不错，我突然有个很棒的点子...🤔"
                else -> "沙发沙发(^o^)~"
            },
            avatarResId = R.drawable.image1,

            isLiked = listOf(true, false).random(),
            likeCount = (5..150).random(),
            isFavorites = listOf(true, false).random()
        )
    }
}

suspend fun fetchItemData(itemId: String): BackendMediaData {
    delay(330)
    return when (itemId) {
        "1" -> BackendMediaData(
            id = "1",
            type = CardContentType.VIDEO,
            content = "啊跨境电商客家话",
            title = "大自然的奇观：落日下的海岸线",
            followCount = 500,
            commentCount = 120,
            likeCount = 3567,
            shareCount = 45,
            favoriteCount = 890,
            author = "旅行者小明",
            avatar = "https://your_avatar_url_1.jpg",
            time = "1小时前",
            videoUrl = "https://your_video_url_1.mp4"
        )

        "2" -> BackendMediaData(
            id = "2",
            type = CardContentType.TEXT,
            title = "关于未来的五个大胆预测",
            content = "啊跨境电商客家话",
            followCount = 800,
            commentCount = 345,
            likeCount = 987,
            shareCount = 112,
            favoriteCount = 234,
            author = "科技狂人",
            avatar = "https://your_avatar_url_2.jpg",
            time = "3天前"
        )

        else -> BackendMediaData(
            id = "666",
            type = CardContentType.TEXT,
            title = "关于未来的五个大胆预测",
            content = "啊跨境电商客家话",
            followCount = 800,
            commentCount = 345,
            likeCount = 987,
            shareCount = 112,
            favoriteCount = 234,
            author = "科技狂人",
            avatar = "https://your_avatar_url_2.jpg",
            time = "3天前"
        )
    }
}